package com.szq.netty.codec;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;

import java.nio.charset.Charset;
import java.util.List;

/**
 * @ClassName: MyDecoder
 * @Description: 自定义解码器
 * @Author: szq
 * @Date: 2021-11-10 16:25:55
 */
public class MyDecoder extends ByteToMessageDecoder {

    //数据包基础长度
    private final int BASE_LENGTH = 4;

    @Override
    protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf in, List<Object> list) {
        //基础长度不足，直接返回
        if (in.readableBytes() < BASE_LENGTH){
            return;
        }

        //记录包头位置
        int beginIndex;

        while (true){
            //获取包头开始的index
            beginIndex = in.readerIndex();
            //标记包头开始的index
            in.markReaderIndex();
            //读到了协议的开始标志，结束while循环
            if (in.readByte() == 0x02){
                break;
            }

            //未读到包头，略过一个字节
            //每次略过一个字节，去读取，包头信息的开始标记
            in.resetReaderIndex();
            in.readByte();
            // 当略过，一个字节之后，
            // 数据包的长度，又变得不满足
            // 此时，应该结束。等待后面的数据到达
            if (in.readableBytes() < BASE_LENGTH){
                return;
            }
        }
        
        //剩余长度不足可读取数量
        int readableCount = in.readableBytes();
        if (readableCount <= 1){
            in.readerIndex(beginIndex);
            return;
        }
        
        //长度域占4字节，读取int
        ByteBuf byteBuf1 = in.readBytes(1);
        String msgLengthStr = byteBuf1.toString(Charset.forName("GBK"));
        int msgLength = Integer.parseInt(msgLengthStr);

        //剩余长度不足可读取数量
        readableCount = in.readableBytes();
        if (readableCount <= 1){
            in.readerIndex(beginIndex);
            return;
        }

        ByteBuf msgContent = in.readBytes(msgLength);

        //如果没有结尾标识，还原指针位置
        byte end = in.readByte();
        if (end != 0x03){
            in.readerIndex(beginIndex);
            return;
        }

        list.add(msgContent.toString(Charset.forName("GBK")));
    }
}
